package com.ecoolex.ying.space.admin.graphql;

import java.util.List;
import java.util.stream.Collectors;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.lang.NonNull;
import com.google.common.collect.Lists;
import com.alibaba.fastjson.JSONArray;
import com.ecoolex.framework.common.enums.ResultCode;
import com.ecoolex.framework.common.pojo.Page;
import com.ecoolex.framework.common.pojo.Pagination;
import com.ecoolex.framework.common.pojo.Sorting;
import com.ecoolex.framework.common.util.Assert;
import com.ecoolex.framework.common.util.BeanUtil;
import com.ecoolex.framework.common.util.Check;
import com.ecoolex.framework.modularize.api.auth.admin.AdminMemberAuthority;
import com.ecoolex.framework.modularize.api.auth.annotation.AdminAuthoritativeRegister;
import com.ecoolex.framework.modularize.api.service.storage.FileSize;
import com.ecoolex.framework.modularize.api.service.storage.MimeType;
import com.ecoolex.framework.modularize.api.service.storage.StorageInfo;
import com.ecoolex.framework.modularize.api.service.storage.StorageService;
import com.ecoolex.framework.modularize.api.service.storage.Upload;
import com.ecoolex.framework.modularize.api.service.storage.UploadLimit;
import com.ecoolex.framework.modularize.api.service.storage.UploadSource;
import com.ecoolex.framework.web.api.graphql2.annotation.GraphQL2Module;
import com.ecoolex.framework.web.api.graphql2.annotation.MutationField;
import com.ecoolex.framework.web.api.graphql2.annotation.QueryField;
import com.ecoolex.framework.web.api.graphql2.annotation.Source;
import com.ecoolex.framework.web.api.graphql2.annotation.TypeField;
import com.ecoolex.framework.web.api.graphql2.annotation.GraphQL2Module.Type;
import com.ecoolex.ying.space.admin.core.AdminConstant;
import com.ecoolex.ying.space.entity.GoodsCategory;
import com.ecoolex.ying.space.entity.OutsourcingGoods.Column;
import com.ecoolex.ying.space.entity.OutsourcingGoodsWithBLOBs;
import com.ecoolex.ying.space.pojo.AddOutsourcingGoodsDTO;
import com.ecoolex.ying.space.pojo.EditOutsourcingGoodsDTO;
import com.ecoolex.ying.space.ws.GoodsCategoryService;
import com.ecoolex.ying.space.ws.OutsourcingGoodsService;

@GraphQL2Module(type = Type.Admin, description = "外购商品管理")
@AdminAuthoritativeRegister(parentKey = AdminConstant.AUTH_MODULE_KEY, key = OutsourcingGoodsGraphql.AUTH, name = "外购商品管理")
public class OutsourcingGoodsGraphql {
	
	public static final String AUTH = AdminConstant.AUTH_MODULE_KEY + "-OUTSOURCINGGOODS";
	
	@Autowired
	private StorageService storageService;
	
	@Autowired
	private OutsourcingGoodsService outsourcingGoodsService;
	
	@Autowired
	private GoodsCategoryService goodsCategoryService;
	
	@TypeField(type = OutsourcingGoodsWithBLOBs.class, field = "coverImage", description = "列表图片")
	public StorageInfo coverImage(@Source OutsourcingGoodsWithBLOBs source) {
		return storageService.get(source.getCoverImage());
	}
	
	@TypeField(type = OutsourcingGoodsWithBLOBs.class, field = "images", description = "商品图片")
	public List<StorageInfo> images(@Source OutsourcingGoodsWithBLOBs source) {
		JSONArray array = JSONArray.parseArray(source.getImages());
		List<String> storageIdLsit = array.toJavaList(String.class);
		return storageIdLsit.stream().map(storageId -> storageService.get(storageId)).collect(Collectors.toList());
	}
	
	@TypeField(type = OutsourcingGoodsWithBLOBs.class, field = "goodsCategory", description = "商品分类")
	public GoodsCategory goodsCategory(@Source OutsourcingGoodsWithBLOBs source) {
		return goodsCategoryService.getCategoryById(source.getCategoryId());
	}
	
	@TypeField(type = OutsourcingGoodsWithBLOBs.class, field = "canOnline", description = "能上线")
	public boolean canOnline(@Source OutsourcingGoodsWithBLOBs source) {
		return !source.getOnline();
	}
	
	@TypeField(type = OutsourcingGoodsWithBLOBs.class, field = "canOffline", description = "能下线")
	public boolean canOffline(@Source OutsourcingGoodsWithBLOBs source) {
		return outsourcingGoodsService.canOfflineOutsourcingGoods(source.getOutsourcingGoodsId());
	}
	
	@TypeField(type = OutsourcingGoodsWithBLOBs.class, field = "canDel", description = "能删除")
	public boolean canDel(@Source OutsourcingGoodsWithBLOBs source) {
		OutsourcingGoodsWithBLOBs goodsWithBLOBs = outsourcingGoodsService.getOutsourcingGoodsById(source.getOutsourcingGoodsId());
		return !goodsWithBLOBs.getOnline();
	}
	
	@TypeField(type = OutsourcingGoodsWithBLOBs.class, field = "canEdit", description = "能编辑")
	public boolean canEdit(@Source OutsourcingGoodsWithBLOBs source) {
		OutsourcingGoodsWithBLOBs goodsWithBLOBs = outsourcingGoodsService.getOutsourcingGoodsById(source.getOutsourcingGoodsId());
		return !goodsWithBLOBs.getOnline();
	}
	
	private static final String AUTH_GET = AUTH + "-GET";
	
	@QueryField(field = "outsourcingGoods", description = "外购商品详情")
	@AdminAuthoritativeRegister(parentKey = AUTH, key = AUTH_GET, name = "外购商品详情")
	public OutsourcingGoodsWithBLOBs get(@NonNull Integer outsourcingGoodsId,AdminMemberAuthority user) {
		user.assertLogin();
		return outsourcingGoodsService.getOutsourcingGoodsById(outsourcingGoodsId);
	}
	
	private static final String AUTH_QUERY = AUTH + "-QUERY";
	
	@QueryField(field = "outsourcingGoodsList", description = "外购商品列表")
	@AdminAuthoritativeRegister(parentKey = AUTH, key = AUTH_QUERY, name = "外购商品列表")
	public Pagination<OutsourcingGoodsWithBLOBs> query(String name,Boolean online,@NonNull Sorting[] sorts, @NonNull Page page, AdminMemberAuthority user) {
		user.assertLogin();
		return outsourcingGoodsService.queryOutsourcingGoods(name,online, sorts, page);
	}
	
	@MutationField(field = "uploadCoverImage", description = { "上传列表图片" })
	public StorageInfo uploadCoverImage(@NonNull Upload request, AdminMemberAuthority user) {
		if (!user.auth(AUTH_ADD) && !user.auth(AUTH_EDIT)) {
			user.notAuthority();
		}
		UploadSource uploadSource = new UploadSource("OutsourcingGoods","CoverImage");
        UploadLimit uploadLimit = new UploadLimit();
        uploadLimit.setMaxSize(FileSize.MB.byteLength(2));
        uploadLimit.setAllowMimeType(MimeType.IMAGE.commons());
        
        return storageService.upload(request,uploadSource,uploadLimit);
	}

	@MutationField(field = "uploadGoodsImages", description = { "上传商品图片" })
	public StorageInfo uploadGoodsImages(@NonNull Upload request, AdminMemberAuthority user) {
		if (!user.auth(AUTH_ADD) && !user.auth(AUTH_EDIT)) {
			user.notAuthority();
		}
		UploadSource uploadSource = new UploadSource("OutsourcingGoods","Images");
        UploadLimit uploadLimit = new UploadLimit();
        uploadLimit.setMaxSize(FileSize.MB.byteLength(2));
        uploadLimit.setAllowMimeType(MimeType.IMAGE.commons());
        
        return storageService.upload(request,uploadSource,uploadLimit);
	}
	
	@MutationField(field = "uploadOutsourcingGoodsDetail", description = { "上传详情图片" })
	public StorageInfo uploadDetailImages(@NonNull Upload request, AdminMemberAuthority user) {
		if (!user.auth(AUTH_ADD) && !user.auth(AUTH_EDIT)) {
			user.notAuthority();
		}
		UploadSource uploadSource = new UploadSource("OutsourcingGoods","Detail");
        UploadLimit uploadLimit = new UploadLimit();
        uploadLimit.setMaxSize(FileSize.MB.byteLength(2));
        uploadLimit.setAllowMimeType(MimeType.IMAGE.commons());
        
        return storageService.upload(request,uploadSource,uploadLimit);
	}
	
	private static final String AUTH_ADD = AUTH + "-ADD";
	
	@MutationField(field = "addOutsourcingGoods", description = "添加外购商品")
	@AdminAuthoritativeRegister(parentKey = AUTH, key = AUTH_ADD, name = "添加外购商品")
	public OutsourcingGoodsWithBLOBs addOutsourcingGoods(@NonNull AddOutsourcingGoodsDTO add,AdminMemberAuthority user) {
		user.assertAuth(AUTH_ADD);
		return outsourcingGoodsService.addOutsourcingGoods(add, user.userName());
	}
	
	private static final String AUTH_EDIT = AUTH + "-EDIT";
	
	@MutationField(field = "editOutsourcingGoods", description = "编辑外购商品")
	@AdminAuthoritativeRegister(parentKey = AUTH, key = AUTH_EDIT, name = "编辑外购商品")
	public OutsourcingGoodsWithBLOBs editOutsourcingGoods(@NonNull EditOutsourcingGoodsDTO edit,AdminMemberAuthority user) {
		user.assertAuth(AUTH_EDIT);
		OutsourcingGoodsWithBLOBs old = outsourcingGoodsService.getOutsourcingGoodsById(edit.getOutsourcingGoodsId());
		Assert.isTrue(Check.notNull(old), ResultCode.VERIFY.build(1), "商品不存在");
		
		BeanUtil.copy(edit,
				old,
				Lists.newArrayList(Column.online, Column.deleted, Column.createUser, Column.createTime).stream().map(
					Column::getJavaProperty).toArray(String[]::new));
		return outsourcingGoodsService.editOutsourcingGoods(old, user.userName());
	}
	
	private static final String AUTH_DEL = AUTH + "-DEL";
	
	@MutationField(field = "deleteOutsourcingGoods", description = "删除外购商品")
	@AdminAuthoritativeRegister(parentKey = AUTH, key = AUTH_DEL, name = "删除外购商品")
	public boolean deleteOutsourcingGoods(@NonNull Integer outsourcingGoodsId,AdminMemberAuthority user) {
		user.assertAuth(AUTH_DEL);
		OutsourcingGoodsWithBLOBs old = outsourcingGoodsService.getOutsourcingGoodsById(outsourcingGoodsId);
		Assert.isTrue(Check.notNull(old), ResultCode.VERIFY.build(1), "商品不存在");

		outsourcingGoodsService.deleteOutsourcingGoods(old, user.userName());
		return true;
	}
	
	private static final String AUTH_ONLINE = AUTH + "-ONLINE";
	
	@MutationField(field = "onlineOutsourcingGoods", description = "上线外购商品")
	@AdminAuthoritativeRegister(parentKey = AUTH, key = AUTH_ONLINE, name = "上线外购商品")
	public boolean onlineOutsourcingGoods(@NonNull Integer outsourcingGoodsId,AdminMemberAuthority user) {
		user.assertAuth(AUTH_ONLINE);
		OutsourcingGoodsWithBLOBs old = outsourcingGoodsService.getOutsourcingGoodsById(outsourcingGoodsId);
		Assert.isTrue(Check.notNull(old), ResultCode.VERIFY.build(1), "商品不存在");
		
		outsourcingGoodsService.onlineOutsourcingGoods(old, user.userName());
		return true;
	}
	
	private static final String AUTH_OFFLINE = AUTH + "-OFFLINE";
	
	@MutationField(field = "offlineOutsourcingGoods", description = "下线外购商品")
	@AdminAuthoritativeRegister(parentKey = AUTH, key = AUTH_OFFLINE, name = "下线外购商品")
	public boolean offlineOutsourcingGoods(@NonNull Integer outsourcingGoodsId,AdminMemberAuthority user) {
		user.assertAuth(AUTH_OFFLINE);
		OutsourcingGoodsWithBLOBs old = outsourcingGoodsService.getOutsourcingGoodsById(outsourcingGoodsId);
		Assert.isTrue(Check.notNull(old), ResultCode.VERIFY.build(1), "商品不存在");
		
		outsourcingGoodsService.offlineOutsourcingGoods(old, user.userName());
		return true;
	}
}
